home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / UGPRG.ZIP / DENTHOR / TUT20.DOC < prev    next >
Encoding:
Text File  |  1996-07-27  |  39.2 KB  |  1,482 lines

  1.                    ╒═══════════════════════════════╕
  2.                    │         W E L C O M E         │
  3.                    │  To the VGA Trainer Program   │ │
  4.                    │              By               │ │
  5.                    │      DENTHOR of ASPHYXIA      │ │ │
  6.                    ╘═══════════════════════════════╛ │ │
  7.                      ────────────────────────────────┘ │
  8.                        ────────────────────────────────┘
  9.  
  10.                            --==[ PART 20 ]==--
  11.  
  12.  
  13.  
  14. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  15. ■ Introduction
  16.  
  17. Hi all! It has been a _long_ time since my last trainer (as I am sure many
  18. of you have noticed) A lot has happened between now and the last trainer...
  19. but for once I won't bore you with the details ;) I do have a full time job
  20. though, coding C++ applications.
  21.  
  22. I have taken over the production of the PCGPE from Mark Feldman. He is
  23. mailing all the articles written so far, and as soon as I get them I will
  24. get to work on releasing the PCGPE II. Mark is working on the Windows GPE.
  25.  
  26. This trainer is on 3d hidden face removal and face sorting. I was going to
  27. add shading, but that can wait until a later trainer. For conveniance I
  28. will build on the 3d code from tut 16(?). The maths for face removal is a
  29. bit tricky, but just think back to your old High School trig classes.
  30.  
  31. I have noticed that in my absence, one or two people have started their own
  32. trainer series. Read Hornet DemoNews for a great column by Trixter covering
  33. some of the more tricky demo effects.
  34.  
  35. Well, on with the trainer!
  36.  
  37.  
  38. If you would like to contact me, or the team, there are many ways you
  39. can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
  40.                   on the ASPHYXIA BBS.
  41.             2) Write to :  Grant Smith
  42.                            P.O.Box 270 Kloof
  43.                            3640
  44.                            Natal
  45.                            South Africa
  46.             3) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
  47.                   call during varsity). Call +27-31-73-2129 if you call
  48.                   from outside South Africa. (It's YOUR phone bill ;-))
  49.             4) Write to denthor@beastie.cs.und.ac.za in E-Mail.
  50.             5) Write to asphyxia@beastie.cs.und.ac.za to get to all of
  51.                us at once.
  52.  
  53. NB : If you are a representative of a company or BBS, and want ASPHYXIA
  54.        to do you a demo, leave mail to me; we can discuss it.
  55. NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
  56.         quite lonely and want to meet/help out/exchange code with other demo
  57.         groups. What do you have to lose? Leave a message here and we can work
  58.         out how to transfer it. We really want to hear from you!
  59.  
  60. http://goth.vironix.co.za/~denthor                     (WWW)
  61. ftp.eng.ufl.edu pub/msdos/demos/code/graph/tutor       (FTP)
  62.  
  63.  
  64. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  65. ■  Face Sorting
  66.  
  67. There are many ways to sort faces in a 3d object. For now, I will show you
  68. just about the easiest one of the lot.
  69.  
  70. Say you have to polygons....
  71.  
  72.                 ------P1
  73.  
  74.            ------------------P2
  75.  
  76.                    Eye
  77.  
  78. As you can see, P1 has to be drawn before P2. The easiest way to do this is
  79. as follows:
  80.  
  81. On startup, find the mid point of each of the polys, through the easy
  82. equations,
  83.         x = (P2.1.x + P2.2.x + P2.3.x + p2.4.x)/4
  84.         y = (P2.1.y + P2.2.y + P2.3.y + p2.4.y)/4
  85.         z = (P2.1.z + P2.2.z + P2.3.z + p2.4.z)/4
  86.  
  87. NOTE : For a triangle you would obviously only use three points and divide
  88. by three.
  89.  
  90. Anyway, now you have the X,Y,Z of the midpoint of the polygon. You can then
  91. rotate this point with the others. When it comes time to draw, you can
  92. compare the resulting Z of the midpoint, sort all of the Z items, and then
  93. draw them from back to front.
  94.  
  95. In the sample program I use a simple bubble sort... basically, I check the
  96. first two values against each other, and swap them if the first is bigger
  97. then the second. I continue doing this to all the numbers until I run
  98. through the entire list without swapping once. Bubble sorts are standard
  99. seven computer science topics... perhaps borrow a text book to find out
  100. more about them and other (better) sorting methods.
  101.  
  102. The above isn't perfect, but it should work 90% of the time. But it still
  103. means that when you are drawing a cube, you have to draw all 6 sides every
  104. frame, even though only three or so are visible. That is where hidden face
  105. removal comes in...
  106.  
  107. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  108. ■  Hidden Face Removal
  109.  
  110. Pick up something square. A stiffy disk will do fine. Face it towards you,
  111. and number all the corners from one to four in a clockwise direction.
  112.  
  113.                 1 +-------------+ 2
  114.                   |             |
  115.                   |             |
  116.                   |             |
  117.                   |             |
  118.                 4 +-------------+ 3
  119.  
  120. Now rotate the stiffy disk on all three axese, making sure that you can
  121. still see the front of the disk. You will notice that whenever you can see
  122. the front of the disk, the four points are still in alphabetical order. Now
  123. rotate it so that you can see the back of the stiffy. Your points will now
  124. be :
  125.  
  126.                 2 +-------------+ 1
  127.                   |             |
  128.                   |             |
  129.                   |             |
  130.                   |             |
  131.                 3 +-------------+ 4
  132.  
  133. The points are now anti-clockwise! This means, in it's simplest form, that
  134. if you define all your poygon points in a clockwise order, when drawing you
  135. ignore the polys that are anticlockwise. (Obviously when you define the 3d
  136. object, you define the polygons facing away from you in an anticlockwise
  137. order)
  138.  
  139. To find out weather a poly's points are clockwise or not, we need to find
  140. it's normal. Here is where things start getting fun.
  141.  
  142. In school, you are told that a normal is perpendicular to the plane. In
  143. ascii :
  144.                       | Normal
  145.                       |
  146.                       |
  147.         --------------------------- Polygon
  148.  
  149. As you can see, the normal is at 90 degrees to the surface of the poly. We
  150. must extend this to three dimensions for our polygons. You'll have to trust
  151. me on that, I can't draw it in ascii :)
  152.  
  153. To find a normal, you only need three points from your poly (ABC) :
  154. A(x0,y0,z0), B(X1,Y1,Z1), C(X2,Y2,Z2)
  155.  
  156. then the vector normal = AB^AC = (Xn,Yn,Zn) with
  157.         Xn=(y1-y0)(z0-z2)-(z1-z0)(y0-y2)
  158.         Yn=(z1-z0)(x0-x2)-(x1-x0)(z0-z2)
  159.         Zn=(x1-x0)(y0-y2)-(y1-y0)(x0-x2)
  160.  
  161. We are interested in the Z normal, so we will use the function :
  162.   normal:=(x1-x0)(y0-y2)-(y1-y0)(x0-x2);
  163.  
  164. The result is something of a sine wave when you rotate the poly in three
  165. dimensions. A negative value means that the poly is facing you, a posotive
  166. value means that it is pointing away.
  167.  
  168. The above means that with a mere two muls you can discount an entire poly
  169. and not draw it. This method is perfect for "closed" objects such as cubes
  170. etc.
  171.  
  172. I am anything but a maths teacher, so go borrow someones math book to find
  173. out more about surface normals. Trust me, there is a lot more written about
  174. them then you think.
  175.  
  176. An extension of calculating your normal is finding out about light-sourcing
  177. your polygons. Watch for more information in one of the next few tutors.
  178.  
  179.  
  180. A combination of the above two routines should work quite nicely in
  181. creating 3d objects with little or no overlapping. The example file will
  182. show you the two methods and how well they work.
  183.  
  184.  
  185. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  186. ■  In closing
  187.  
  188. As you can see, the above was quite easy. I have a few ideas for tut 21, so
  189. keep watch for it. Also keep an eye open for PCGPE ][ (but don't mail me
  190. asking when it's due! I already get too many of those! ;-)
  191.  
  192. My sister got married a few days ago. The worst part was that I was forced
  193. to cut my hair. My hair was quite long (slightly longer then when the pic
  194. on my web page was taken), and it is all quite depressing. Anyway, the
  195. wedding was great, so it wasn't all for nothing.
  196.  
  197. I hope to get tut 21 and possibly 22 out before christmas, but I will be on
  198. holiday from the 18th. I will be in Cape Town sometime after christmas day
  199. for a week or two, so if you're there I'll meet you on the cable car :-)
  200.  
  201. I wrote a quote for this tut, but I have decided I didn't like it. I'll try
  202. do better for tut 21 ;)
  203.  
  204. Byeeeee.....
  205.   - Denthor
  206.       14-12-95
  207.  
  208. PS. I seem to have lost my list of distribution sites... could you all
  209. re-mail me your details? Thanks.
  210. Unit GFX3;
  211.  
  212.  
  213. INTERFACE
  214.  
  215. USES crt;
  216. CONST VGA = $A000;
  217.  
  218. TYPE Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }
  219.      VirtPtr = ^Virtual;                  { Pointer to the virtual screen }
  220.  
  221. VAR Virscr : VirtPtr;                     { Our first Virtual screen }
  222.     Vaddr  : word;                        { The segment of our virtual screen}
  223.     Scr_Ofs : Array[0..199] of Word;
  224.  
  225. Procedure SetMCGA;
  226.    { This procedure gets you into 320x200x256 mode. }
  227. Procedure SetText;
  228.    { This procedure returns you to text mode.  }
  229. Procedure Cls (Where:word;Col : Byte);
  230.    { This clears the screen to the specified color }
  231. Procedure SetUpVirtual;
  232.    { This sets up the memory needed for the virtual screen }
  233. Procedure ShutDown;
  234.    { This frees the memory used by the virtual screen }
  235. procedure flip(source,dest:Word);
  236.    { This copies the entire screen at "source" to destination }
  237. Procedure Pal(Col,R,G,B : Byte);
  238.    { This sets the Red, Green and Blue values of a certain color }
  239. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  240.   { This gets the Red, Green and Blue values of a certain color }
  241. procedure WaitRetrace;
  242.    {  This waits for a vertical retrace to reduce snow on the screen }
  243. Procedure Hline (x1,x2,y:word;col:byte;where:word);
  244.    { This draws a horizontal line from x1 to x2 on line y in color col }
  245. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  246.   { This draws a solid line from a,b to c,d in colour col }
  247. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  248.    { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  249.      in color col }
  250. Function rad (theta : real) : real;
  251.    {  This calculates the degrees of an angle }
  252. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
  253.    { This puts a pixel on the screen by writing directly to memory. }
  254. Function Getpixel (X,Y : Integer; where:word) :Byte;
  255.    { This gets the pixel on the screen by reading directly to memory. }
  256. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  257.   { This loads the cel 'filename' into the pointer scrptr }
  258. Procedure LoadPal (FileName : string);
  259.   { This loads in an Autodesk Animator V1 pallette file }
  260.  
  261. IMPLEMENTATION
  262.  
  263. {──────────────────────────────────────────────────────────────────────────}
  264. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  265. BEGIN
  266.   asm
  267.      mov        ax,0013h
  268.      int        10h
  269.   end;
  270. END;
  271.  
  272. {──────────────────────────────────────────────────────────────────────────}
  273. Procedure SetText;  { This procedure returns you to text mode.  }
  274. BEGIN
  275.   asm
  276.      mov        ax,0003h
  277.      int        10h
  278.   end;
  279. END;
  280.  
  281. {──────────────────────────────────────────────────────────────────────────}
  282. Procedure Cls (Where:word;Col : Byte); assembler;
  283.    { This clears the screen to the specified color }
  284. asm
  285.    push    es
  286.    mov     cx, 32000;
  287.    mov     es,[where]
  288.    xor     di,di
  289.    mov     al,[col]
  290.    mov     ah,al
  291.    rep     stosw
  292.    pop     es
  293. End;
  294.  
  295. {──────────────────────────────────────────────────────────────────────────}
  296. Procedure SetUpVirtual;
  297.    { This sets up the memory needed for the virtual screen }
  298. BEGIN
  299.   GetMem (VirScr,64000);
  300.   vaddr := seg (virscr^);
  301. END;
  302.  
  303. {──────────────────────────────────────────────────────────────────────────}
  304. Procedure ShutDown;
  305.    { This frees the memory used by the virtual screen }
  306. BEGIN
  307.   FreeMem (VirScr,64000);
  308. END;
  309.  
  310. {──────────────────────────────────────────────────────────────────────────}
  311. procedure flip(source,dest:Word); assembler;
  312.   { This copies the entire screen at "source" to destination }
  313. asm
  314.   push    ds
  315.   mov     ax, [Dest]
  316.   mov     es, ax
  317.   mov     ax, [Source]
  318.   mov     ds, ax
  319.   xor     si, si
  320.   xor     di, di
  321.   mov     cx, 32000
  322.   rep     movsw
  323.   pop     ds
  324. end;
  325.  
  326. {──────────────────────────────────────────────────────────────────────────}
  327. Procedure Pal(Col,R,G,B : Byte); assembler;
  328.   { This sets the Red, Green and Blue values of a certain color }
  329. asm
  330.    mov    dx,3c8h
  331.    mov    al,[col]
  332.    out    dx,al
  333.    inc    dx
  334.    mov    al,[r]
  335.    out    dx,al
  336.    mov    al,[g]
  337.    out    dx,al
  338.    mov    al,[b]
  339.    out    dx,al
  340. end;
  341.  
  342. {──────────────────────────────────────────────────────────────────────────}
  343. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  344.   { This gets the Red, Green and Blue values of a certain color }
  345. Var
  346.    rr,gg,bb : Byte;
  347. Begin
  348.    asm
  349.       mov    dx,3c7h
  350.       mov    al,col
  351.       out    dx,al
  352.  
  353.       add    dx,2
  354.  
  355.       in     al,dx
  356.       mov    [rr],al
  357.       in     al,dx
  358.       mov    [gg],al
  359.       in     al,dx
  360.       mov    [bb],al
  361.    end;
  362.    r := rr;
  363.    g := gg;
  364.    b := bb;
  365. end;
  366.  
  367. {──────────────────────────────────────────────────────────────────────────}
  368. procedure WaitRetrace; assembler;
  369.   {  This waits for a vertical retrace to reduce snow on the screen }
  370. label
  371.   l1, l2;
  372. asm
  373.     mov dx,3DAh
  374. l1:
  375.     in al,dx
  376.     and al,08h
  377.     jnz l1
  378. l2:
  379.     in al,dx
  380.     and al,08h
  381.     jz  l2
  382. end;
  383.  
  384. {──────────────────────────────────────────────────────────────────────────}
  385. Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
  386.   { This draws a horizontal line from x1 to x2 on line y in color col }
  387. asm
  388.   mov   ax,where
  389.   mov   es,ax
  390.   mov   ax,y
  391.   mov   di,ax
  392.   shl   ax,8
  393.   shl   di,6
  394.   add   di,ax
  395.   add   di,x1
  396.  
  397.   mov   al,col
  398.   mov   ah,al
  399.   mov   cx,x2
  400.   sub   cx,x1
  401.   shr   cx,1
  402.   jnc   @start
  403.   stosb
  404. @Start :
  405.   rep   stosw
  406. end;
  407.  
  408. {──────────────────────────────────────────────────────────────────────────}
  409. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  410.   { This draws a solid line from a,b to c,d in colour col }
  411.   function sgn(a:real):integer;
  412.   begin
  413.        if a>0 then sgn:=+1;
  414.        if a<0 then sgn:=-1;
  415.        if a=0 then sgn:=0;
  416.   end;
  417. var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
  418. begin
  419.      u:= c - a;
  420.      v:= d - b;
  421.      d1x:= SGN(u);
  422.      d1y:= SGN(v);
  423.      d2x:= SGN(u);
  424.      d2y:= 0;
  425.      m:= ABS(u);
  426.      n := ABS(v);
  427.      IF NOT (M>N) then
  428.      BEGIN
  429.           d2x := 0 ;
  430.           d2y := SGN(v);
  431.           m := ABS(v);
  432.           n := ABS(u);
  433.      END;
  434.      s := m shr 1;
  435.      FOR i := 0 TO m DO
  436.      BEGIN
  437.           putpixel(a,b,col,where);
  438.           s := s + n;
  439.           IF not (s<m) THEN
  440.           BEGIN
  441.                s := s - m;
  442.                a:= a + d1x;
  443.                b := b + d1y;
  444.           END
  445.           ELSE
  446.           BEGIN
  447.                a := a + d2x;
  448.                b := b + d2y;
  449.           END;
  450.      end;
  451. END;
  452.  
  453.  
  454. {──────────────────────────────────────────────────────────────────────────}
  455. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  456.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  457.     in color col }
  458. var
  459.   x:integer;
  460.   mny,mxy:integer;
  461.   mnx,mxx,yc:integer;
  462.   mul1,div1,
  463.   mul2,div2,
  464.   mul3,div3,
  465.   mul4,div4:integer;
  466.  
  467. begin
  468.   mny:=y1; mxy:=y1;
  469.   if y2<mny then mny:=y2;
  470.   if y2>mxy then mxy:=y2;
  471.   if y3<mny then mny:=y3;
  472.   if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
  473.   if y4<mny then mny:=y4;
  474.   if y4>mxy then mxy:=y4;
  475.  
  476.   if mny<0 then mny:=0;
  477.   if mxy>199 then mxy:=199;
  478.   if mny>199 then exit;
  479.   if mxy<0 then exit;        { Verticle range checking }
  480.  
  481.   mul1:=x1-x4; div1:=y1-y4;
  482.   mul2:=x2-x1; div2:=y2-y1;
  483.   mul3:=x3-x2; div3:=y3-y2;
  484.   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }
  485.  
  486.   for yc:=mny to mxy do
  487.     begin
  488.       mnx:=320;
  489.       mxx:=-1;
  490.       if (y4>=yc) or (y1>=yc) then
  491.         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
  492.           if not(y4=y1) then
  493.             begin
  494.               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
  495.               if x<mnx then
  496.                 mnx:=x;
  497.               if x>mxx then
  498.                 mxx:=x;       { Set point as start or end of horiz line }
  499.             end;
  500.       if (y1>=yc) or (y2>=yc) then
  501.         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
  502.           if not(y1=y2) then
  503.             begin
  504.               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
  505.               if x<mnx then
  506.                 mnx:=x;
  507.               if x>mxx then
  508.                 mxx:=x;       { Set point as start or end of horiz line }
  509.             end;
  510.       if (y2>=yc) or (y3>=yc) then
  511.         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
  512.           if not(y2=y3) then
  513.             begin
  514.               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
  515.               if x<mnx then
  516.                 mnx:=x;
  517.               if x>mxx then
  518.                 mxx:=x;       { Set point as start or end of horiz line }
  519.             end;
  520.       if (y3>=yc) or (y4>=yc) then
  521.         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
  522.           if not(y3=y4) then
  523.             begin
  524.               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
  525.               if x<mnx then
  526.                 mnx:=x;
  527.               if x>mxx then
  528.                 mxx:=x;       { Set point as start or end of horiz line }
  529.             end;
  530.       if mnx<0 then
  531.         mnx:=0;
  532.       if mxx>319 then
  533.         mxx:=319;          { Range checking on horizontal line }
  534.       if mnx<=mxx then
  535.         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }
  536.     end;
  537.   end;
  538.  
  539. {──────────────────────────────────────────────────────────────────────────}
  540. Function rad (theta : real) : real;
  541.   {  This calculates the degrees of an angle }
  542. BEGIN
  543.   rad := theta * pi / 180
  544. END;
  545.  
  546. {──────────────────────────────────────────────────────────────────────────}
  547. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
  548.   { This puts a pixel on the screen by writing directly to memory. }
  549. asm
  550.    mov  ax,where
  551.    mov  es,ax
  552.    mov  bx,[y]
  553.    shl  bx,1
  554.    mov  di,word ptr [Scr_Ofs + bx]
  555.    add  di,[x]
  556.    mov  al,[col]
  557.    mov  es:[di],al
  558. end;
  559.  
  560.  
  561. {──────────────────────────────────────────────────────────────────────────}
  562. Function Getpixel (X,Y : Integer; where:word):byte; assembler;
  563.   { This puts a pixel on the screen by writing directly to memory. }
  564. asm
  565.    mov  ax,where
  566.    mov  es,ax
  567.    mov  bx,[y]
  568.    shl  bx,1
  569.    mov  di,word ptr [Scr_Ofs + bx]
  570.    add  di,[x]
  571.    mov  al,es:[di]
  572. end;
  573.  
  574. {──────────────────────────────────────────────────────────────────────────}
  575. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  576.   { This loads the cel 'filename' into the pointer scrptr }
  577. var
  578.   Fil : file;
  579.   Buf : array [1..1024] of byte;
  580.   BlocksRead, Count : word;
  581. begin
  582.   assign (Fil, FileName);
  583.   reset (Fil, 1);
  584.   BlockRead (Fil, Buf, 800);    { Read and ignore the 800 byte header }
  585.   Count := 0;
  586.   BlocksRead := $FFFF;
  587.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  588.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  589.     Count := Count + 1024;
  590.   end;
  591.   close (Fil);
  592. end;
  593.  
  594.  
  595. procedure LoadPal (FileName : string);
  596. var
  597.   F:file;
  598.   loop1:integer;
  599.   pall:array[0..255,1..3] of byte;
  600. begin
  601.   assign (F, FileName);
  602.   reset (F,1);
  603.   blockread (F, pall,768);
  604.   close (F);
  605.   for loop1 := 0 to 255 do
  606.     Pal(loop1,pall[loop1,1],pall[loop1,2],pall[loop1,3]);
  607. end;
  608.  
  609.  
  610. VAR Loop1:integer;
  611.  
  612. BEGIN
  613.   For Loop1 := 0 to 199 do
  614.     Scr_Ofs[Loop1] := Loop1 * 320;
  615. END.{$X+}
  616. USES Crt,GFX3;
  617.  
  618. CONST VGA = $A000;
  619.       maxpolys = 18;
  620.  
  621.             A : Array [1..maxpolys,1..4,1..3] of integer =
  622.         (
  623.          ((-10, -10, 10 ),
  624.           (10 , -10, 10 ),
  625.           (10 , 10 , 10 ),
  626.           (-10, 10 , 10 )),
  627.  
  628.          ((-10, 10 , -10),
  629.           (10 , 10 , -10),
  630.           (10 , -10, -10),
  631.           (-10, -10, -10)),
  632.  
  633.          ((-10, 10 , 10 ),
  634.           (-10, 10 , -10),
  635.           (-10, -10, -10),
  636.           (-10, -10, 10 )),
  637.  
  638.          ((10 , -10, 10 ),
  639.           (10 , -10, -10),
  640.           (10 , 10 , -10),
  641.           (10 , 10 , 10 )),
  642.  
  643.          ((10 , 10 , 10 ),
  644.           (10 , 10 , -10),
  645.           (-10, 10 , -10),
  646.           (-10, 10 , 10 )),
  647.  
  648.          ((-10, -10, 10 ),
  649.           (-10, -10, -10),
  650.           (10 , -10, -10),
  651.           (10 , -10, 10 )),
  652.  
  653. (*********)
  654.  
  655.          ((-10, -10,-20 ),
  656.           (10 , -10,-20 ),
  657.           (10 , 10 ,-20 ),
  658.           (-10, 10 ,-20 )),
  659.  
  660.          ((-10, 10 , -30),
  661.           (10 , 10 , -30),
  662.           (10 , -10, -30),
  663.           (-10, -10, -30)),
  664.  
  665.          ((-10, 10 ,-20 ),
  666.           (-10, 10 , -30),
  667.           (-10, -10, -30),
  668.           (-10, -10,-20 )),
  669.  
  670.          ((10 , -10,-20 ),
  671.           (10 , -10, -30),
  672.           (10 , 10 , -30),
  673.           (10 , 10 ,-20 )),
  674.  
  675.          ((10 , 10 ,-20 ),
  676.           (10 , 10 , -30),
  677.           (-10, 10 , -30),
  678.           (-10, 10 ,-20 )),
  679.  
  680.          ((-10, -10,-20 ),
  681.           (-10, -10, -30),
  682.           (10 , -10, -30),
  683.           (10 , -10,-20 )),
  684.  
  685. (*********)
  686.  
  687.          ((-30, -10, 10 ),
  688.           (-20, -10, 10 ),
  689.           (-20, 10 , 10 ),
  690.           (-30, 10 , 10 )),
  691.  
  692.          ((-30, 10 , -10),
  693.           (-20, 10 , -10),
  694.           (-20, -10, -10),
  695.           (-30, -10, -10)),
  696.  
  697.          ((-30, 10 , 10 ),
  698.           (-30, 10 , -10),
  699.           (-30, -10, -10),
  700.           (-30, -10, 10 )),
  701.  
  702.          ((-20, -10, 10 ),
  703.           (-20, -10, -10),
  704.           (-20, 10 , -10),
  705.           (-20, 10 , 10 )),
  706.  
  707.          ((-20, 10 , 10 ),
  708.           (-20, 10 , -10),
  709.           (-30, 10 , -10),
  710.           (-30, 10 , 10 )),
  711.  
  712.          ((-30, -10, 10 ),
  713.           (-30, -10, -10),
  714.           (-20, -10, -10),
  715.           (-20, -10, 10 ))
  716.         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
  717.             { (X2,Y2,Z2) ... for the 4 points of a poly }
  718.  
  719.       XOfs = 100;
  720.       YOfs = 160;
  721.  
  722.  
  723. Type Point = Record
  724.                x,y,z:integer;                { The data on every point we rotate}
  725.              END;
  726.  
  727.  
  728. VAR Lines : Array [1..maxpolys,1..4] of Point; { The base object to be rotated }
  729.     Translated : Array [1..maxpolys,1..4] of Point; { The rotated object }
  730.     centre, tcentre : Array [1..maxpolys] of Point;
  731.     Order : Array[1..maxpolys] of integer;
  732.     lookup : Array [0..360,1..2] of integer; { Our sin and cos lookup table }
  733.     poly : array [0..199,1..2] of integer;
  734.     ytopclip,ybotclip:integer;  {where to clip our polys to}
  735.     xoff,yoff,zoff:integer;
  736.  
  737.  
  738. {──────────────────────────────────────────────────────────────────────────}
  739. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  740. BEGIN
  741.   asm
  742.      mov        ax,0013h
  743.      int        10h
  744.   end;
  745. END;
  746.  
  747.  
  748. {──────────────────────────────────────────────────────────────────────────}
  749. Procedure Hline (x1,x2,y:integer;col:byte;where:word); assembler;
  750.   { This draws a horizontal line from x1 to x2 on line y in color col }
  751. asm
  752.   mov   ax,x1
  753.   cmp   ax,0
  754.   jge   @X1Okay
  755.   mov   x1,0
  756. @X1Okay :
  757.  
  758.   mov   ax,x2
  759.   cmp   ax,319
  760.   jle   @X2Okay
  761.   mov   x2,319
  762. @X2Okay :
  763.  
  764.   mov   ax,x1
  765.   cmp   ax,x2
  766.   jg    @Exit
  767.  
  768.   mov   ax,where
  769.   mov   es,ax
  770.   mov   ax,y
  771.   mov   di,ax
  772.   shl   ax,8
  773.   shl   di,6
  774.   add   di,ax
  775.   add   di,x1
  776.  
  777.   mov   al,col
  778.   mov   ah,al
  779.   mov   cx,x2
  780.   sub   cx,x1
  781.   shr   cx,1
  782.   jnc   @start
  783.   stosb
  784. @Start :
  785.   rep   stosw
  786. @Exit :
  787. end;
  788.  
  789.  
  790. {──────────────────────────────────────────────────────────────────────────}
  791. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  792.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  793.     in color col }
  794. var miny,maxy:integer;
  795.     loop1:integer;
  796.  
  797. Procedure doside (x1,y1,x2,y2:integer);
  798.   { This scans the side of a polygon and updates the poly variable }
  799. VAR temp:integer;
  800.     x,xinc:integer;
  801.     loop1:integer;
  802. BEGIN
  803.   if y1=y2 then exit;
  804.   if y2<y1 then BEGIN
  805.     temp:=y2;
  806.     y2:=y1;
  807.     y1:=temp;
  808.     temp:=x2;
  809.     x2:=x1;
  810.     x1:=temp;
  811.   END;
  812.   xinc:=((x2-x1) shl 7) div (y2-y1);
  813.   x:=x1 shl 7;
  814.   for loop1:=y1 to y2 do BEGIN
  815.     if (loop1>(ytopclip)) and (loop1<(ybotclip)) then BEGIN
  816.       if (x shr 7<poly[loop1,1]) then poly[loop1,1]:=x shr 7;
  817.       if (x shr 7>poly[loop1,2]) then poly[loop1,2]:=x shr 7;
  818.     END;
  819.     x:=x+xinc;
  820.   END;
  821. END;
  822.  
  823. begin
  824.   asm
  825.     mov   si,offset poly
  826.     mov   cx,200
  827. @Loop1:
  828.     mov   ax,32766
  829.     mov   ds:[si],ax
  830.     inc   si
  831.     inc   si
  832.     mov   ax,-32767
  833.     mov   ds:[si],ax
  834.     inc   si
  835.     inc   si
  836.     loop  @loop1
  837.   end;     { Setting the minx and maxx values to extremes }
  838.   miny:=y1;
  839.   maxy:=y1;
  840.   if y2<miny then miny:=y2;
  841.   if y3<miny then miny:=y3;
  842.   if y4<miny then miny:=y4;
  843.   if y2>maxy then maxy:=y2;
  844.   if y3>maxy then maxy:=y3;
  845.   if y4>maxy then maxy:=y4;
  846.   if miny<ytopclip then miny:=ytopclip;
  847.   if maxy>ybotclip then maxy:=ybotclip;
  848.   if (miny>199) or (maxy<0) then exit;
  849.  
  850.   Doside (x1,y1,x2,y2);
  851.   Doside (x2,y2,x3,y3);
  852.   Doside (x3,y3,x4,y4);
  853.   Doside (x4,y4,x1,y1);
  854.  
  855.   for loop1:= miny to maxy do
  856.     hline (poly[loop1,1],poly[loop1,2],loop1,color,where);
  857. end;
  858.  
  859.  
  860. {──────────────────────────────────────────────────────────────────────────}
  861. Procedure SetUpPoints;
  862.   { This creates the lookup table }
  863. VAR loop1,loop2:integer;
  864. BEGIN
  865.   For loop1:=0 to 360 do BEGIN
  866.     lookup [loop1,1]:=round(sin (rad (loop1))*16384);
  867.     lookup [loop1,2]:=round(cos (rad (loop1))*16384);
  868.   END;
  869.   For loop1:=1 to maxpolys do BEGIN
  870.     centre[loop1].x := (lines[loop1,1].x + lines[loop1,2].x +
  871.                         lines[loop1,3].x + lines[loop1,4].x) div 4;
  872.     centre[loop1].y := (lines[loop1,1].y + lines[loop1,2].y +
  873.                         lines[loop1,3].y + lines[loop1,4].y) div 4;
  874.     centre[loop1].z := (lines[loop1,1].z + lines[loop1,2].z +
  875.                         lines[loop1,3].z + lines[loop1,4].z) div 4;
  876.   END;
  877. END;
  878.  
  879.  
  880. {──────────────────────────────────────────────────────────────────────────}
  881. Procedure RotatePoints (x,Y,z:Integer);
  882.   { This rotates the objecct in lines to translated }
  883. VAR loop1,loop2:integer;
  884.     a,b,c:integer;
  885. BEGIN
  886.   For loop1:=1 to maxpolys do BEGIN
  887.     for loop2:=1 to 4 do BEGIN
  888.       b:=lookup[y,2];
  889.       c:=lines[loop1,loop2].x;
  890.       asm
  891.         mov   ax,b
  892.         imul  c
  893.         sal   ax,1
  894.         rcl   dx,1
  895.         sal   ax,1
  896.         rcl   dx,1
  897.         mov   a,dx
  898.       end;
  899.       b:=lookup[y,1];
  900.       c:=lines[loop1,loop2].z;
  901.       asm
  902.         mov   ax,b
  903.         imul  c
  904.         sal   ax,1
  905.         rcl   dx,1
  906.         sal   ax,1
  907.         rcl   dx,1
  908.         add   a,dx
  909.       end;
  910.       translated[loop1,loop2].x:=a;
  911.       translated[loop1,loop2].y:=lines[loop1,loop2].y;
  912.       b:=-lookup[y,1];
  913.       c:=lines[loop1,loop2].x;
  914.       asm
  915.         mov   ax,b
  916.         imul  c
  917.         sal   ax,1
  918.         rcl   dx,1
  919.         sal   ax,1
  920.         rcl   dx,1
  921.         mov   a,dx
  922.       end;
  923.       b:=lookup[y,2];
  924.       c:=lines[loop1,loop2].z;
  925.       asm
  926.         mov   ax,b
  927.         imul  c
  928.         sal   ax,1
  929.         rcl   dx,1
  930.         sal   ax,1
  931.         rcl   dx,1
  932.         add   a,dx
  933.       end;
  934.       translated[loop1,loop2].z:=a;
  935.  
  936.  
  937.       if x<>0 then BEGIN
  938.         b:=lookup[x,2];
  939.         c:=translated[loop1,loop2].y;
  940.         asm
  941.           mov   ax,b
  942.           imul  c
  943.           sal   ax,1
  944.           rcl   dx,1
  945.           sal   ax,1
  946.           rcl   dx,1
  947.           mov   a,dx
  948.         end;
  949.         b:=lookup[x,1];
  950.         c:=translated[loop1,loop2].z;
  951.         asm
  952.           mov   ax,b
  953.           imul  c
  954.           sal   ax,1
  955.           rcl   dx,1
  956.           sal   ax,1
  957.           rcl   dx,1
  958.           sub   a,dx
  959.         end;
  960.         b:=lookup[x,1];
  961.         c:=translated[loop1,loop2].y;
  962.         translated[loop1,loop2].y:=a;
  963.         asm
  964.           mov   ax,b
  965.           imul  c
  966.           sal   ax,1
  967.           rcl   dx,1
  968.           sal   ax,1
  969.           rcl   dx,1
  970.           mov   a,dx
  971.         end;
  972.         b:=lookup[x,2];
  973.         c:=translated[loop1,loop2].z;
  974.         asm
  975.           mov   ax,b
  976.           imul  c
  977.           sal   ax,1
  978.           rcl   dx,1
  979.           sal   ax,1
  980.           rcl   dx,1
  981.           add   a,dx
  982.         end;
  983.         translated[loop1,loop2].z:=a;
  984.       END;
  985.  
  986.  
  987.  
  988.  
  989.       if z<>0 then BEGIN
  990.         b:=lookup[z,2];
  991.         c:=translated[loop1,loop2].x;
  992.         asm
  993.           mov   ax,b
  994.           imul  c
  995.           sal   ax,1
  996.           rcl   dx,1
  997.           sal   ax,1
  998.           rcl   dx,1
  999.           mov   a,dx
  1000.         end;
  1001.         b:=lookup[z,1];
  1002.         c:=translated[loop1,loop2].y;
  1003.         asm
  1004.           mov   ax,b
  1005.           imul  c
  1006.           sal   ax,1
  1007.           rcl   dx,1
  1008.           sal   ax,1
  1009.           rcl   dx,1
  1010.           sub   a,dx
  1011.         end;
  1012.         b:=lookup[z,1];
  1013.         c:=translated[loop1,loop2].x;
  1014.         translated[loop1,loop2].x:=a;
  1015.         asm
  1016.           mov   ax,b
  1017.           imul  c
  1018.           sal   ax,1
  1019.           rcl   dx,1
  1020.           sal   ax,1
  1021.           rcl   dx,1
  1022.           mov   a,dx
  1023.         end;
  1024.         b:=lookup[z,2];
  1025.         c:=translated[loop1,loop2].y;
  1026.         asm
  1027.           mov   ax,b
  1028.           imul  c
  1029.           sal   ax,1
  1030.           rcl   dx,1
  1031.           sal   ax,1
  1032.           rcl   dx,1
  1033.           add   a,dx
  1034.         end;
  1035.         translated[loop1,loop2].y:=a;
  1036.       END;
  1037.     END;
  1038.   END;
  1039.  
  1040.  
  1041. {******************}
  1042.   For loop1:=1 to maxpolys do BEGIN
  1043.     b:=lookup[y,2];
  1044.     c:=centre[loop1].x;
  1045.     asm
  1046.       mov   ax,b
  1047.       imul  c
  1048.       sal   ax,1
  1049.       rcl   dx,1
  1050.       sal   ax,1
  1051.       rcl   dx,1
  1052.       mov   a,dx
  1053.     end;
  1054.     b:=lookup[y,1];
  1055.     c:=centre[loop1].z;
  1056.     asm
  1057.       mov   ax,b
  1058.       imul  c
  1059.       sal   ax,1
  1060.       rcl   dx,1
  1061.       sal   ax,1
  1062.       rcl   dx,1
  1063.       add   a,dx
  1064.     end;
  1065.     tcentre[loop1].x:=a;
  1066.     tcentre[loop1].y:=centre[loop1].y;
  1067.     b:=-lookup[y,1];
  1068.     c:=centre[loop1].x;
  1069.     asm
  1070.       mov   ax,b
  1071.       imul  c
  1072.       sal   ax,1
  1073.       rcl   dx,1
  1074.       sal   ax,1
  1075.       rcl   dx,1
  1076.       mov   a,dx
  1077.     end;
  1078.     b:=lookup[y,2];
  1079.     c:=centre[loop1].z;
  1080.     asm
  1081.       mov   ax,b
  1082.       imul  c
  1083.       sal   ax,1
  1084.       rcl   dx,1
  1085.       sal   ax,1
  1086.       rcl   dx,1
  1087.       add   a,dx
  1088.     end;
  1089.     tcentre[loop1].z:=a;
  1090.  
  1091.  
  1092.     if x<>0 then BEGIN
  1093.       b:=lookup[x,2];
  1094.       c:=tcentre[loop1].y;
  1095.       asm
  1096.         mov   ax,b
  1097.         imul  c
  1098.         sal   ax,1
  1099.         rcl   dx,1
  1100.         sal   ax,1
  1101.         rcl   dx,1
  1102.         mov   a,dx
  1103.       end;
  1104.       b:=lookup[x,1];
  1105.       c:=tcentre[loop1].z;
  1106.       asm
  1107.         mov   ax,b
  1108.         imul  c
  1109.         sal   ax,1
  1110.         rcl   dx,1
  1111.         sal   ax,1
  1112.         rcl   dx,1
  1113.         sub   a,dx
  1114.       end;
  1115.       b:=lookup[x,1];
  1116.       c:=tcentre[loop1].y;
  1117.       tcentre[loop1].y:=a;
  1118.       asm
  1119.         mov   ax,b
  1120.         imul  c
  1121.         sal   ax,1
  1122.         rcl   dx,1
  1123.         sal   ax,1
  1124.         rcl   dx,1
  1125.         mov   a,dx
  1126.       end;
  1127.       b:=lookup[x,2];
  1128.       c:=tcentre[loop1].z;
  1129.       asm
  1130.         mov   ax,b
  1131.         imul  c
  1132.         sal   ax,1
  1133.         rcl   dx,1
  1134.         sal   ax,1
  1135.         rcl   dx,1
  1136.         add   a,dx
  1137.       end;
  1138.       tcentre[loop1].z:=a;
  1139.     END;
  1140.  
  1141.  
  1142.  
  1143.  
  1144.     if z<>0 then BEGIN
  1145.       b:=lookup[z,2];
  1146.       c:=tcentre[loop1].x;
  1147.       asm
  1148.         mov   ax,b
  1149.         imul  c
  1150.         sal   ax,1
  1151.         rcl   dx,1
  1152.         sal   ax,1
  1153.         rcl   dx,1
  1154.         mov   a,dx
  1155.       end;
  1156.       b:=lookup[z,1];
  1157.       c:=tcentre[loop1].y;
  1158.       asm
  1159.         mov   ax,b
  1160.         imul  c
  1161.         sal   ax,1
  1162.         rcl   dx,1
  1163.         sal   ax,1
  1164.         rcl   dx,1
  1165.         sub   a,dx
  1166.       end;
  1167.       b:=lookup[z,1];
  1168.       c:=tcentre[loop1].x;
  1169.       tcentre[loop1].x:=a;
  1170.       asm
  1171.         mov   ax,b
  1172.         imul  c
  1173.         sal   ax,1
  1174.         rcl   dx,1
  1175.         sal   ax,1
  1176.         rcl   dx,1
  1177.         mov   a,dx
  1178.       end;
  1179.       b:=lookup[z,2];
  1180.       c:=tcentre[loop1].y;
  1181.       asm
  1182.         mov   ax,b
  1183.         imul  c
  1184.         sal   ax,1
  1185.         rcl   dx,1
  1186.         sal   ax,1
  1187.         rcl   dx,1
  1188.         add   a,dx
  1189.       end;
  1190.       tcentre[loop1].y:=a;
  1191.     END;
  1192.   END;
  1193. END;
  1194.  
  1195.  
  1196.  
  1197. {──────────────────────────────────────────────────────────────────────────}
  1198. Procedure DrawPoints;
  1199.   { This draws the translated object to the virtual screen }
  1200. VAR loop1,loop2:Integer;
  1201.     temp, normal:integer;
  1202.     nx:integer;
  1203.     tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4:integer;
  1204. BEGIN
  1205.   For loop2:=1 to maxpolys do BEGIN
  1206.     loop1:=order[loop2];
  1207.     If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0)
  1208.        and (translated[loop1,3].z+zoff<0) and (translated[loop1,4].z+zoff<0)
  1209.        then BEGIN
  1210.       temp:=round (translated[loop1,1].z)+zoff;
  1211.       nx:=translated[loop1,1].X;
  1212.       asm
  1213.         mov   ax,nx
  1214.         mov   dx,ax
  1215.         sal   ax,8
  1216.         sar   dx,8
  1217.         idiv  temp
  1218.         add   ax,YOfs
  1219.         mov   nx,ax
  1220.       end;
  1221.       tx1:=nx;
  1222.       nx:=translated[loop1,1].Y;
  1223.       asm
  1224.         mov   ax,nx
  1225.         mov   dx,ax
  1226.         sal   ax,8
  1227.         sar   dx,8
  1228.         idiv  temp
  1229.         add   ax,XOfs
  1230.         mov   nx,ax
  1231.       end;
  1232.       ty1:=nx;
  1233.  
  1234.  
  1235.       temp:=round (translated[loop1,2].z)+zoff;
  1236.       nx:=translated[loop1,2].X;
  1237.       asm
  1238.         mov   ax,nx
  1239.         mov   dx,ax
  1240.         sal   ax,8
  1241.         sar   dx,8
  1242.         idiv  temp
  1243.         add   ax,YOfs
  1244.         mov   nx,ax
  1245.       end;
  1246.       tx2:=nx;
  1247.       nx:=translated[loop1,2].Y;
  1248.       asm
  1249.         mov   ax,nx
  1250.         mov   dx,ax
  1251.         sal   ax,8
  1252.         sar   dx,8
  1253.         idiv  temp
  1254.         add   ax,XOfs
  1255.         mov   nx,ax
  1256.       end;
  1257.       ty2:=nx;
  1258.  
  1259.  
  1260.       temp:=round (translated[loop1,3].z)+zoff;
  1261.       nx:=translated[loop1,3].X;
  1262.       asm
  1263.         mov   ax,nx
  1264.         mov   dx,ax
  1265.         sal   ax,8
  1266.         sar   dx,8
  1267.         idiv  temp
  1268.         add   ax,YOfs
  1269.         mov   nx,ax
  1270.       end;
  1271.       tx3:=nx;
  1272.       nx:=translated[loop1,3].Y;
  1273.       asm
  1274.         mov   ax,nx
  1275.         mov   dx,ax
  1276.         sal   ax,8
  1277.         sar   dx,8
  1278.         idiv  temp
  1279.         add   ax,XOfs
  1280.         mov   nx,ax
  1281.       end;
  1282.       ty3:=nx;
  1283.  
  1284.  
  1285.       temp:=round (translated[loop1,4].z)+zoff;
  1286.       nx:=translated[loop1,4].X;
  1287.       asm
  1288.         mov   ax,nx
  1289.         mov   dx,ax
  1290.         sal   ax,8
  1291.         sar   dx,8
  1292.         idiv  temp
  1293.         add   ax,YOfs
  1294.         mov   nx,ax
  1295.       end;
  1296.       tx4:=nx;
  1297.       nx:=translated[loop1,4].Y;
  1298.       asm
  1299.         mov   ax,nx
  1300.         mov   dx,ax
  1301.         sal   ax,8
  1302.         sar   dx,8
  1303.         idiv  temp
  1304.         add   ax,XOfs
  1305.         mov   nx,ax
  1306.       end;
  1307.       ty4:=nx;
  1308.  
  1309.       normal:=(ty1-ty3)*(tx2-tx1)-(tx1-tx3)*(ty2-ty1);
  1310.       if normal<0 then
  1311.         drawpoly (tx1,ty1,tx2,ty2,tx3,ty3,tx4,ty4,loop1,vaddr);
  1312.     END;
  1313.   END;
  1314. END;
  1315.  
  1316.  
  1317.  
  1318. {──────────────────────────────────────────────────────────────────────────}
  1319. Procedure SortPoints;
  1320. VAR loop1,curpos, temp:integer;
  1321. BEGIN
  1322.   for loop1:=1 to maxpolys do BEGIN
  1323.     order[loop1]:=loop1;
  1324.   END;
  1325.   curpos := 1;
  1326.   while curpos<maxpolys do BEGIN
  1327.     if tcentre[curpos].z > tcentre[curpos+1].z then BEGIN
  1328.       temp := tcentre[curpos+1].x;
  1329.       tcentre[curpos+1].x := tcentre[curpos].x;
  1330.       tcentre[curpos].x := temp;
  1331.  
  1332.       temp := tcentre[curpos+1].y;
  1333.       tcentre[curpos+1].y := tcentre[curpos].y;
  1334.       tcentre[curpos].y := temp;
  1335.  
  1336.       temp := tcentre[curpos+1].z;
  1337.       tcentre[curpos+1].z := tcentre[curpos].z;
  1338.       tcentre[curpos].z := temp;
  1339.  
  1340.       temp := order[curpos+1];
  1341.       order[curpos+1] := order[curpos];
  1342.       order[curpos] := temp;
  1343.  
  1344.       curpos:=0;
  1345.     END;
  1346.     curpos:=curpos+1;
  1347.   END;
  1348. END;
  1349.  
  1350.  
  1351. {──────────────────────────────────────────────────────────────────────────}
  1352. Procedure MoveAround;
  1353.   { This is the main display procedure. }
  1354. VAR deg,deg2,loop1,loop2:integer;
  1355.     ch:char;
  1356.  
  1357. BEGIN
  1358.   pal (1,  0, 0,63);
  1359.   pal (2,  0,32,63);
  1360.   pal (3, 32, 0,63);
  1361.   pal (4, 32,32,63);
  1362.   pal (5,  0,63,63);
  1363.   pal (6, 32,63,63);
  1364.  
  1365.   pal ( 7,  0,63, 0);
  1366.   pal ( 8,  0,63,32);
  1367.   pal ( 9, 32,63, 0);
  1368.   pal (10, 32,63,32);
  1369.   pal (11,  0,63,63);
  1370.   pal (12, 32,63,63);
  1371.  
  1372.   pal (13, 63, 0, 0);
  1373.   pal (14, 63,32, 0);
  1374.   pal (15, 63, 0,32);
  1375.   pal (16, 63,32,32);
  1376.   pal (17, 63,63, 0);
  1377.   pal (18, 63,63,32);
  1378. {  for loop1:=1 to 15 do
  1379.     pal (loop1,0,loop1*4+3,63-(loop1*4+3));}
  1380.   pal (100,50,50,50);
  1381.  
  1382.   deg:=0;
  1383.   deg2:=0;
  1384.   ch:=#0;
  1385.   Cls (vaddr,0);
  1386.   For loop1:=1 to maxpolys do
  1387.     For loop2:=1 to 4 do BEGIN
  1388.       Lines [loop1,loop2].x:=a [loop1,loop2,1]*8;
  1389.       Lines [loop1,loop2].y:=a [loop1,loop2,2]*8;
  1390.       Lines [loop1,loop2].z:=a [loop1,loop2,3]*8;
  1391.     END;
  1392.  
  1393.   SetUpPoints;
  1394.  
  1395.   cls (vaddr,0);
  1396.   cls (vga,0);
  1397.   Xoff := 160;
  1398.   Yoff:=100;
  1399.   zoff:=-500;
  1400.  
  1401.   ytopclip:=101;
  1402.   ybotclip:=100;
  1403.   line (0,100,319,100,100,vga);
  1404.   delay (2000);
  1405.   for loop1:=1 to 25 do BEGIN
  1406.     RotatePoints (deg2,deg,deg2);
  1407.     SortPoints;
  1408.     DrawPoints;
  1409.     line (0,ytopclip,319,ytopclip,100,vaddr);
  1410.     line (0,ybotclip,319,ybotclip,100,vaddr);
  1411.     flip (vaddr,vga);
  1412.     cls (vaddr,0);
  1413.     deg:=(deg+5) mod 360;
  1414.     deg2:=(deg2+1) mod 360;
  1415.     ytopclip:=ytopclip-4;
  1416.     ybotclip:=ybotclip+4;
  1417.   END;
  1418.   Repeat
  1419.     if keypressed then ch:=upcase (Readkey);
  1420.     RotatePoints (deg2,deg,deg2);
  1421.     SortPoints;
  1422.     DrawPoints;
  1423.     line (0,0,319,0,100,vaddr);
  1424.     line (0,199,319,199,100,vaddr);
  1425.     flip (vaddr,vga);
  1426.     cls (vaddr,0);
  1427.     deg:=(deg+5) mod 360;
  1428.     deg2:=(deg2+3) mod 360;
  1429.   Until ch=#27;
  1430.   for loop1:=1 to 25 do BEGIN
  1431.     ytopclip:=ytopclip+4;
  1432.     ybotclip:=ybotclip-4;
  1433.     RotatePoints (deg2,deg,deg2);
  1434.     SortPoints;
  1435.     DrawPoints;
  1436.     line (0,ytopclip,319,ytopclip,100,vaddr);
  1437.     line (0,ybotclip,319,ybotclip,100,vaddr);
  1438.     flip (vaddr,vga);
  1439.     cls (vaddr,0);
  1440.     deg:=(deg+5) mod 360;
  1441.     deg2:=(deg2+1) mod 360;
  1442.   END;
  1443. END;
  1444.  
  1445.  
  1446. BEGIN
  1447.   clrscr;
  1448.   writeln ('Welcome to the twentieth(sp) trainer! This one is on face sorting');
  1449.   writeln ('and back face removal.');
  1450.   writeln;
  1451.   writeln ('Just hit a key to view the 3d shape. You will notice that you');
  1452.   writeln ('won''t see any of the faces you shouldn''t see :-)');
  1453.   writeln ('The code is based on that from the glenzing tut, so you should');
  1454.   writeln ('be able to understand it fairly quickly.');
  1455.   writeln;
  1456.   writeln;
  1457.   writeln;
  1458.   write ('Hit any key to continue ...');
  1459.   readkey;
  1460.   SetUpVirtual;
  1461.   SetMCGA;
  1462.   MoveAround;
  1463.   SetText;
  1464.   ShutDown;
  1465.   Writeln ('All done. This concludes the twentieth sample program in the ASPHYXIA');
  1466.   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
  1467.   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS.I also occasinally');
  1468.   Writeln ('RSAProg, comp.lang.pascal and comp.sys.ibm.pc.demos. E-mail me at :');
  1469.   Writeln ('    denthor@goth.vironix.co.za');
  1470.   Writeln ('The numbers are available in the main text. You may also write to me at:');
  1471.   Writeln ('             Grant Smith');
  1472.   Writeln ('             P.O. Box 270');
  1473.   Writeln ('             Kloof');
  1474.   Writeln ('             3640');
  1475.   Writeln ('             Natal');
  1476.   Writeln ('             South Africa');
  1477.   Writeln ('I hope to hear from you soon!');
  1478.   Writeln; Writeln;
  1479.   Write   ('Hit any key to exit ...');
  1480.   readkey;
  1481. END.
  1482.